﻿using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using SDL2;


namespace THZFrm {
    public partial class Form1 : Form {
        private delegate void SetCloseback();
        private delegate void StatusChange(IntPtr status);    //获取关闭状态
        private delegate void GetStarParaData(IntPtr starpara, bool bstar);

        private StatusChange statusChange = null;
        private GetStarParaData getStarParaData = null;

        private bool bEnd = false;

        private SDLClass sdlSDI1Class;
        private const int nDelHeight = 15;  //groupBox要保留的高度，否则看不到字了
        string lstVideoName = "";     //视频设备名称
        bool bCameraOpen = false;           //摄像头是否已经打开
        bool bVideoCapture = false;         //是否在显示视频
        int nConnected = 0;                 //是否与服务器连接，同时也是连接失败计数器

        public Form1() {
            InitializeComponent();

            statusChange = new StatusChange(updateStatus);
            getStarParaData = new GetStarParaData(UpdateStarParaStatus);

            sdlSDI1Class = new SDLClass(groupBox1, nDelHeight);
            
            Init(sdlSDI1Class.getData, sdlSDI1Class.getData, statusChange, getStarParaData);
            SetIsHost(true);
            
            //timer1.Enabled = false;
        }

        //更新关闭状态，这么做主要是为了防止dll线程释放不干净
        private void updateStatus(IntPtr status) {
            //this.Invoke((EventHandler)(delegate {
            //    if(bClose) {
            //        CloseForm();
            //    }
            //}));
            int[] s = new int[5];
            Marshal.Copy(status, s, 0, 5);
            if(s[0] == 0) {
                // 服务器连接中断
                stslabel.Text = "未连接服务器";
                ConnectSrvBtn.Text = "连接服务器";
                // TODO 重连逻辑需要重写，目前会导致程序无法正常关闭
                //if(nConnected > 0) {
                //    // 非主动中断
                //    if(nConnected > 5) {
                //        // 最多重试5次
                //        nConnected = 0;
                //    } else {
                //        // 等待1秒后自动重连上一次的IP和端口
                //        Delay(1000);
                //        ConnectTCPSrv(0, null);
                //        nConnected++;
                //    }
                //}
                nConnected = 0;
            } else {
                nConnected = 1;
                stslabel.Text = "已连接服务器";
                ConnectSrvBtn.Text = "断开连接";
            }
        }

        private void CloseForm() {
            try {
                if(this.InvokeRequired) {
                    SetCloseback d = new SetCloseback(CloseForm);
                    this.Invoke(d);
                } else {
                    Close();
                }
            } catch(Exception ex) {
                ;
            }
        }

        private void Form1_Closing(object sender, FormClosingEventArgs e) {
            if(!bEnd) {
                bEnd = true;

                freeSpace();
            }

            if(timer1.Enabled) {
                timer1.Stop();
            }
        }

        //初始化摄像头设备和MAC地址信息
        private void Form1_Shown(object sender, EventArgs e) {
            IntPtr ptr = GetVideoDeviceInfo();
            lstVideoName = Marshal.PtrToStringAnsi(ptr);
            string[] strName = lstVideoName.Split(';');
            foreach(string val in strName) {
                videoComboBox.Items.Add(val);
                videoComboBox.SelectedIndex = 0;
            }
        }

        //窗口发生变化时，更新视频窗口的大小
        private void Form1_SizeChanged(object sender, EventArgs e) {
            if(null != sdlSDI1Class) {
                sdlSDI1Class.SetDisplayRect(groupBox1, nDelHeight);
            }
        }

        //释放空间
        public void freeSpace() {
            stopBtn_Click(null, null);
            if(nConnected > 0) {
                openMACBtn_Click(null, null);
            }
            CleanMemory();
            SDL.SDL_Quit();
        }

        //开始播放视频
        private void startBtn_Click(object sender, EventArgs e) {
            startBtn.Enabled = false;
            if(!bCameraOpen) {
                if(videoComboBox.SelectedIndex == -1) {
                    MessageBox.Show("请选择摄像头!");
                    startBtn.Enabled = true;
                    return;
                }
                if(OpenVideoDevice(videoComboBox.SelectedItem.ToString()) != 0) {
                    MessageBox.Show("打开摄像头失败!");
                    startBtn.Enabled = true;
                    return;
                }
                bCameraOpen = true;
            }
            if(bVideoCapture) {
                PauseCapture();
                bVideoCapture = false;
                startBtn.Text = "开始";
            } else {
                StartCapture();
                //bVideoCapture = true;
                //startBtn.Text = "暂停";
                stopBtn.Enabled = true;
            }
        }

        //停止播放视频
        private void stopBtn_Click(object sender, EventArgs e) {
            stopBtn.Enabled = false;
            StopCapture();
            bCameraOpen = false;
            bVideoCapture = false;
            startBtn.Enabled = true;
            //startBtn.Text = "开始";
        }

        //连接TCP服务器
        private void openMACBtn_Click(object sender, EventArgs e) {
            if(nConnected == 0) {
                if(-1 == ConnectTCPSrv(Convert.ToInt32(SrvPortTextbox.Text.ToString()), SrvIPTextBox.Text.ToString())) {
                    MessageBox.Show("连接服务器失败！");
                } else {
                    //nConnected = 1;
                }
            } else {
                nConnected = 0;
                DisConnetTCPSrv();
            }
        }

        private void videoComboBox_SelectedIndexChanged(object sender, EventArgs e) {
            if(bCameraOpen) {
                stopBtn_Click(sender, e);
                startBtn_Click(sender, e);
            }
            return;
        }
        private void Delay(int time) {
            DateTime last = DateTime.Now;
            do {
                Application.DoEvents();
            } while((DateTime.Now - last).TotalMilliseconds < time);
        }

        private void UpdateStarParaStatus(IntPtr starpara, bool bstar) {

        }

        private void timer1_Tick(object sender, EventArgs e) {
        }

        private double GetRandomDouble(Random ran, double minValue, double maxValue) {
            return ran.NextDouble() * (maxValue - minValue) + minValue;
        }

        private int GetRandomNum() {
            Random rnd = new Random();
            int n = rnd.Next(60, 90);
            return n;
        }

        #region DLL传递函数以及参数
        [DllImport("VideoDecodeDll", CharSet = CharSet.Ansi)]
        private static extern void Init(
            SDLClass.GetData getDataSDI1, SDLClass.GetData getDataSDI2, StatusChange sChange, GetStarParaData StarParaData);
        [DllImport("VideoDecodeDll", CharSet = CharSet.Ansi)]
        private static extern IntPtr GetVideoDeviceInfo();
        [DllImport("VideoDecodeDll", CharSet = CharSet.Ansi)]
        private static extern int OpenVideoDevice(string strVideoName);
        [DllImport("VideoDecodeDll", CharSet = CharSet.Ansi)]
        private static extern int CloseVideoDevice();
        [DllImport("VideoDecodeDll", CharSet = CharSet.Ansi)]
        private extern static int StartCapture();
        [DllImport("VideoDecodeDll", CharSet = CharSet.Ansi)]
        private extern static int PauseCapture();
        [DllImport("VideoDecodeDll", CharSet = CharSet.Ansi)]
        private extern static int StopCapture();
        [DllImport("VideoDecodeDll", CharSet = CharSet.Ansi)]
        private extern static void CleanMemory();
        [DllImport("VideoDecodeDll", CharSet = CharSet.Ansi)]
        private static extern int ConnectTCPSrv(int nSrvPort, string strSrvIPAddr);
        [DllImport("VideoDecodeDll", CharSet = CharSet.Ansi)]
        private static extern void DisConnetTCPSrv();
        //[DllImport("VideoDecodeDll", CharSet = CharSet.Ansi)]
        //private static extern int ConfigCeJu(int nCejuSts);
        //[DllImport("VideoDecodeDll", CharSet = CharSet.Ansi)]
        //private static extern void SetCompVal(double dbCompVal);
        //[DllImport("VideoDecodeDll", CharSet = CharSet.Ansi)]
        //private static extern void ConfigThreshold(int[] thres_str);
        //[DllImport("VideoDecodeDll", CharSet = CharSet.Ansi)]
        //private extern static int SendJunHeng(bool b);
        [DllImport("VideoDecodeDll", CharSet = CharSet.Ansi)]
        private static extern void SetIsHost(bool b);
        #endregion
    }
}
